package com.zs.toolbox.web2j.system.core.controller.auth;


import com.zs.toolbox.web2j.common.exception.WtResponses;
import com.zs.toolbox.web2j.common.request.WtBaseTokenReqeust;
import com.zs.toolbox.web2j.common.response.WtBaseResponse;
import com.zs.toolbox.web2j.common.web.WtAuthContext;
import com.zs.toolbox.web2j.common.web.WtBaseController;
import com.zs.toolbox.web2j.db.config.OnlyReadDbOperation;
import com.zs.toolbox.web2j.system.message.client.WtMessageClient;
import com.zs.toolbox.web2j.system.core.constant.WtEVcodePurpose;
import com.zs.toolbox.web2j.system.core.converts.WtUserConverters;
import com.zs.toolbox.web2j.system.core.entity.WtUserEntity;
import com.zs.toolbox.web2j.system.core.entity.WtUserWithRoleEntity;
import com.zs.toolbox.web2j.system.core.request.*;
import com.zs.toolbox.web2j.system.core.service.WtUserService;
import com.zs.toolbox.web2j.system.core.service.WtVcodeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import static com.zs.toolbox.web2j.common.exception.WtResponses.SUCCESS;

/**
 * <p>
 * 用户基本信息操作
 * </p>
 *
 * @author eric.zhang
 * @since 2018-09-21
 */
@RestController
@RequestMapping("/api/v1/user/auth")
@Api(value = "认证安全管理", description = "认证安全管理")
@Slf4j
public class WtSystemAuthController extends WtBaseController {


    @Autowired
    WtUserService wtUserService;

    @Autowired
    WtMessageClient wtMessageClient;

    @Autowired
    WtVcodeService wtVcodeService;


    @ApiOperation("获得当前用户信息")
    @RequestMapping(value = "getDetail", method = {RequestMethod.POST, RequestMethod.GET})
    @PreAuthorize("isAuthenticated()")
    public WtBaseResponse<WtUserWithRoleEntity> getUserDetail() {
        return new WtBaseResponse<>(wtUserService.getUserWithRoleById(WtAuthContext.getUserId()));
    }

    @ApiOperation(value = "用户登录接口", notes = "通过用户名和密码进行基础登陆操作")
    @RequestMapping(value = "login", method = {RequestMethod.GET, RequestMethod.POST})
    @OnlyReadDbOperation
    WtBaseResponse loginByNameAndPassword(WtUserNamePasswordLoginRequestToken request) {
        this.volidate(request);
        WtUserEntity wtUserEntity = wtUserService.selectByUsernameOrPhoneOrEmail(request.getUserName());

        if (null != wtUserEntity && wtUserService.matchPassword(request.getPassword(), wtUserEntity.getPassword())) {
            String token = wtUserService.createrToken(wtUserEntity);
            return new WtBaseResponse(token);
        } else {
            return WtResponses.E_LOGIN;
        }
    }

    @ApiOperation(value = "获取新TOKEN", notes = "通过TOKEN获取新TOKEN")
    @RequestMapping(value = "refreshToken", method = {RequestMethod.GET, RequestMethod.POST})
    @PreAuthorize("isAuthenticated()")
    WtBaseResponse refreshToken(WtBaseTokenReqeust reqeust) {
        String token = wtUserService.createrToken(wtUserService.getById(WtAuthContext.getUserId()));
        return new WtBaseResponse(token);
    }


    @RequestMapping(value = "findPassword", method = {RequestMethod.POST})
    @ApiOperation(value = "更改密码接口")
    WtBaseResponse findPassword(WtChangePasswordTokenReqeust reqeust) {
        this.volidate(reqeust);
        wtVcodeService.verifyEmailOrPhoneVcode(reqeust.getKey(), reqeust.getVcode());
        wtUserService.changePasswordByPhoneOrEmail(reqeust.getKey(), reqeust.getNewPassword());
        wtVcodeService.clearCacheSendCode(reqeust.getKey());
        return SUCCESS;
    }

    @RequestMapping(value = "genCodeImage", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "用户图像验证码")
    WtBaseResponse genCodeImage(WtImageCodeReqeust reqeust) {
        this.volidate(reqeust);
        String codeBase64Image = wtVcodeService.newImageCode(reqeust.getKey());
        return new WtBaseResponse(codeBase64Image);
    }

    @RequestMapping(value = "sendVCode", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "发送手机/邮箱验证码")
    WtBaseResponse sendVCode(WtSendVCodeReqeust reqeust) {
        this.volidate(reqeust);

        /*此KEY，用于查找对应KEY缓存的图片验证码*/
        String imageCodeKey = "";
        Boolean isPhone = false;
        Boolean isEmail = false;
        if (StringUtils.isNotBlank(reqeust.getEmail())) {
            isEmail = true;
            imageCodeKey = reqeust.getEmail();
        } else if (StringUtils.isNotBlank(reqeust.getPhone())) {
            isPhone = true;
            imageCodeKey = reqeust.getPhone();
        }

        if (reqeust.getNeedCheckImageCode()) {
            wtVcodeService.verifyImageCode(imageCodeKey, reqeust.getImageCode());
        }

        if (isEmail) {
            wtVcodeService.newEmailVcode(WtEVcodePurpose.valueOfCode(reqeust.getVcodeType()), reqeust.getEmail());
        } else if (isPhone) {
            wtVcodeService.newPhoneVcode(WtEVcodePurpose.valueOfCode(reqeust.getVcodeType()), reqeust.getPhone());
        }
        wtVcodeService.clearCacheImageCode(imageCodeKey);
        return SUCCESS;
    }

    @RequestMapping(value = "bindPhone", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "绑定手机号")
    @PreAuthorize("isAuthenticated()")
    WtBaseResponse bindPhone(WtBindPhoneReqeust reqeust) {
        this.volidate(reqeust);
        wtVcodeService.verifyEmailOrPhoneVcode(reqeust.getPhone(), reqeust.getVcode());
        wtUserService.bindPhone(WtAuthContext.getUserId(), reqeust.getPhone());
        wtVcodeService.clearCacheSendCode(reqeust.getPhone());
        return SUCCESS;
    }

    @RequestMapping(value = "unbindPhone", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "解绑手机号")
    @PreAuthorize("isAuthenticated()")
    WtBaseResponse unbindPhone(WtBindPhoneReqeust reqeust) {
        this.volidate(reqeust);
        wtVcodeService.verifyEmailOrPhoneVcode(reqeust.getPhone(), reqeust.getVcode());
        wtUserService.unbindPhone(WtAuthContext.getUserId(), reqeust.getPhone());
        wtVcodeService.clearCacheSendCode(reqeust.getPhone());
        return SUCCESS;
    }

    @RequestMapping(value = "bindEmail", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "绑定邮箱")
    @PreAuthorize("isAuthenticated()")
    WtBaseResponse bindEmail(WtBindEmailReqeust reqeust) {
        this.volidate(reqeust);
        wtVcodeService.verifyEmailOrPhoneVcode(reqeust.getEmail(), reqeust.getVcode());
        wtUserService.bindeEmail(WtAuthContext.getUserId(), reqeust.getEmail());
        wtVcodeService.clearCacheSendCode(reqeust.getEmail());
        return SUCCESS;
    }

    @RequestMapping(value = "unbindEmail", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "解绑邮箱")
    @PreAuthorize("isAuthenticated()")
    WtBaseResponse unbindEmail(WtBindEmailReqeust reqeust) {
        this.volidate(reqeust);
        wtVcodeService.verifyEmailOrPhoneVcode(reqeust.getEmail(), reqeust.getVcode());
        wtUserService.unbindEmail(WtAuthContext.getUserId(), reqeust.getEmail());
        wtVcodeService.clearCacheSendCode(reqeust.getEmail());
        return SUCCESS;
    }

    @RequestMapping(value = "registerUserByPhoneOrEmail", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "邮箱/手机号/注册接口")
    WtBaseResponse registerUserByPhoneOrEmail(WtRegisterByUsernameAndPasswordReqeust reqeust) {
        this.volidate(reqeust);

        /*判断是手机号方式或邮箱方式注册，是邮箱清除无用手机号，是手机号清除无用邮箱*/
        String cacheVcodeKey = "";
        if (StringUtils.isNotBlank(reqeust.getEmail())) {
            cacheVcodeKey = reqeust.getEmail();
            reqeust.setPhone(null);
        } else if (StringUtils.isNotBlank(reqeust.getPhone())) {
            cacheVcodeKey = reqeust.getPhone();
            reqeust.setEmail(null);
        }

        wtVcodeService.verifyEmailOrPhoneVcode(cacheVcodeKey, reqeust.getVcode());
        wtUserService.saveNewUser(WtUserConverters.convertToNewWtUserEntitiy(reqeust));
        wtVcodeService.clearCacheSendCode(cacheVcodeKey);
        return SUCCESS;
    }


}
